/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.tabbedproperties.section;

import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.gef.EditPart;
import org.eclipse.gef.commands.CommandStack;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
import org.eclipse.uml2.uml.Classifier;
import org.eclipse.uml2.uml.ClassifierTemplateParameter;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.ParameterableElement;
import org.eclipse.uml2.uml.TemplateParameterSubstitution;
import org.eclipse.uml2.uml.UMLPackage;

import com.cea.papyrus.core.commands.factories.UMLDi2ElementDeleteFactory;
import com.cea.papyrus.core.editor.CommandStackUtils;
import com.cea.papyrus.core.editpart.IUMLElementEditPart;
import com.cea.papyrus.core.tabbedproperties.PropertyViewSection;
import com.cea.papyrus.core.tabbedproperties.composite.DecoratedTextComposite;
import com.cea.papyrus.core.utils.LookForElement;
import com.cea.papyrus.diagram.classdiagram.commands.ElementOwnedByATemplateParameterSubstitutionCreateCommand;
import com.cea.papyrus.profile.ui.dialogs.ChooseSetAssistedDialog;
import com.cea.papyrus.umlutils.Element;

/**
 * the owned actual parameter section (related to a template parameter substitution)
 */
public class OwnedActualParameterSection extends PropertyViewSection {

	/**
	 * 
	 */
	private DecoratedTextComposite ownedActualParameterComposite;

	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#createControls(org.eclipse.swt.widgets.Composite, org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage)
	 */
	/**
	 * 
	 * 
	 * @param tabbedPropertySheetPage 
	 * @param parent 
	 */
	@Override
	public void createControls(Composite parent,
			TabbedPropertySheetPage tabbedPropertySheetPage) {
		super.createControls(parent, tabbedPropertySheetPage);
		
		final TabbedPropertySheetPage sheetPage = tabbedPropertySheetPage ;
		// creation of the ownedParameteredElement section
		ownedActualParameterComposite = new DecoratedTextComposite("Owned actual") {
			
			public void editText() {
				TemplateParameterSubstitution currentTemplateParameterSubstitution = (TemplateParameterSubstitution)getElement().getUml2Element() ;
				if (!currentTemplateParameterSubstitution.getOwnedActuals().isEmpty()) {
					EditPart selection = null ;
					for (Iterator<EditPart> i=LookForElement.getAllOutlineEditParts().iterator() ; i.hasNext() ; ) {
						EditPart current = i.next() ;
						if (current.getModel() == currentTemplateParameterSubstitution.getOwnedActuals().get(0))
							selection = current ;
					}
					if (selection != null)
						sheetPage.selectionChanged(getPart(), new StructuredSelection(selection)) ;
				}
			}
			
			public void removeButtonPressed() {
				TemplateParameterSubstitution currentTemplateParameterSubstitution = (TemplateParameterSubstitution)this.getElement().getUml2Element() ;
				if (!currentTemplateParameterSubstitution.getOwnedActuals().isEmpty()) {
					CommandStack stack = CommandStackUtils.getCommandStack();
					org.eclipse.gef.commands.Command command = UMLDi2ElementDeleteFactory.eINSTANCE.createCommand((org.eclipse.uml2.uml.Element)currentTemplateParameterSubstitution.getOwnedActuals().get(0)) ;
					Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
					stack.execute(command);
				}
				refresh() ;
			}
			
			public void addButtonPressed() {
				TemplateParameterSubstitution currentTemplateParameterSubstitution = (TemplateParameterSubstitution)this.getElement().getUml2Element() ;
				org.eclipse.gef.commands.Command command = null ;
				CommandStack stack = CommandStackUtils.getCommandStack();
				EClass parameteredElementMetaclass = null ; // the metaclass of the parametered element of the formal parameter (used as a filter for the ChooseFilteredMetaclassDialog)
				parameteredElementMetaclass = currentTemplateParameterSubstitution.getFormal().getParameteredElement().eClass() ;
				if (currentTemplateParameterSubstitution.getFormal() instanceof ClassifierTemplateParameter) {
					if (((ClassifierTemplateParameter)currentTemplateParameterSubstitution.getFormal()).getConstrainingClassifier() != null) {
						parameteredElementMetaclass = ((ClassifierTemplateParameter)currentTemplateParameterSubstitution.getFormal()).getConstrainingClassifier().eClass() ;
					}
				}
				try {
					ownedActualParameterComposite.dispose() ;
					ChooseFilteredMetaclassDialog dialog ;
					dialog = new ChooseFilteredMetaclassDialog(composite.getShell(), 
							"Kind of owned actual to create:", 
							"Selected metaclass:",
							parameteredElementMetaclass);
					dialog.create();
					dialog.setFocus();
					dialog.open();
					if(dialog.getSelectedMetaClass()!=null) {
						String className = dialog.getSelectedMetaClass().getName() ;
						className = "org.eclipse.uml2.uml." + className ;
						command = new ElementOwnedByATemplateParameterSubstitutionCreateCommand(dialog.getSelectedMetaClass(), 
								Class.forName(className), 
								currentTemplateParameterSubstitution) ;
						Assert.isNotNull(stack, "Impossible to adapt current editor into a CommandStack");
						stack.execute(command);
						refresh() ;
					}
				}
				catch (Exception e) {
					e.printStackTrace() ;
				}
			}
			
			public void refresh() {
				if (text.isDisposed()) return ;
				TemplateParameterSubstitution currentTemplateParameterSubstitution = (TemplateParameterSubstitution)this.getElement().getUml2Element() ;
				if (!currentTemplateParameterSubstitution.getActuals().isEmpty()) {
					ParameterableElement actualParameter = (ParameterableElement)currentTemplateParameterSubstitution.getActuals().get(0) ;
					if (!currentTemplateParameterSubstitution.getOwnedActuals().isEmpty()) {
						if (currentTemplateParameterSubstitution.getOwnedActuals().contains(actualParameter)) {
							this.text.setText(((NamedElement)actualParameter).getName()) ;
							this.text.setEnabled(true) ;
							this.removeButton.setEnabled(true) ;
							this.addButton.setEnabled(true) ;
						}
						else {
							this.text.setText("") ;
							this.text.setEnabled(false) ;
							this.addButton.setEnabled(false) ;
							this.removeButton.setEnabled(false) ;
						}
					}
					else {
						this.text.setText("") ;
						this.text.setEnabled(false) ;
						this.addButton.setEnabled(false) ;
						this.removeButton.setEnabled(false) ;
					}
				}
				else {
					this.text.setText("") ;
					this.text.setEnabled(true) ;
					this.addButton.setEnabled(true) ;
					this.removeButton.setEnabled(true) ;
				}
			}
		};
		ownedActualParameterComposite.createContent(parent, tabbedPropertySheetPage.getWidgetFactory());
	}

	/*
	 * @see org.eclipse.ui.views.properties.tabbed.view.ITabbedPropertySection#refresh()
	 */
	/**
	 * 
	 */
	@Override
	public void refresh() {
		if (this.umlElement != null) {
			if (!((TemplateParameterSubstitution)this.umlElement).getActuals().isEmpty()) {
				NamedElement actual = (NamedElement)(((TemplateParameterSubstitution)this.umlElement).getActuals().get(0)) ;
				if (actual.getName()!=null)
					ownedActualParameterComposite.refresh();
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.ui.views.properties.tabbed.AbstractPropertySection#setInput(org.eclipse.ui.IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
	 */
	/**
	 * 
	 * 
	 * @param part 
	 * @param selection 
	 */
	@Override
	public void setInput(IWorkbenchPart part, ISelection selection) {
		super.setInput(part, selection);
		Assert.isTrue(selection instanceof IStructuredSelection);
		Object input = ((IStructuredSelection) selection).getFirstElement();
		if (input instanceof IUMLElementEditPart) {
			org.eclipse.uml2.uml.Element element = ((IUMLElementEditPart) input).getUmlElement();
        	if(element instanceof org.eclipse.uml2.uml.TemplateParameterSubstitution) {
        		Element utilElement = new Element((org.eclipse.uml2.uml.TemplateParameterSubstitution)element);
        		ownedActualParameterComposite.setElement(utilElement) ;
        	}
		}
	}
	
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.core.ui.properties.tabbed.PropertyViewSection#dispose()
	 */
	/**
	 * 
	 */
	public void dispose(){
		super.dispose();
		if(ownedActualParameterComposite!=null)
			ownedActualParameterComposite.dispose();
	}
	
	// ChooseSetAssistedDialog is specialized locally
	protected class ChooseFilteredMetaclassDialog extends ChooseSetAssistedDialog {
		
		private String selectedClassifierName ;
		
		public ChooseFilteredMetaclassDialog(Shell parentShell, String possibleText, String selectedText, EClass filter){
			super(parentShell, possibleText, selectedText) ;
			List filteredMetaclasses = LookForElement.getMetaclasses(filter,false, getElement()) ;
			for (Iterator<Classifier> i = filteredMetaclasses.iterator() ; i.hasNext() ; ){
				Classifier current = i.next();
				if(!selectedElementList.contains(current)) {
					possibleElementList.addElement(current.getName());
				}
			}
		}
		
		// create method is overrided so that up and down buttons are not visible
		// Only one metaclass can be selected, so these features are useless
		public void create() {
			super.create() ;
			downButton.setVisible(false) ;
			upButton.setVisible(false) ;
		}
			
		public void runActionAdd(Object element) {
			super.runActionAdd(element) ;
			selectedClassifierName = new String((String)element) ;
			this.addButton.setEnabled(false) ;
		}
		
		protected void runActionRemove(Object element){
			super.runActionRemove(element) ;
			this.addButton.setEnabled(true) ;
			this.selectedClassifierName = null ;
		}
	
		public void okPressed() {
			if (selectedClassifierName!=null)
				super.okPressed() ;
		}
		
		public void cancelPressed() {
			selectedClassifierName = null ;
			super.cancelPressed() ;
		}
		
		public EClass getSelectedMetaClass() {
			if (selectedClassifierName == null)
				return null ;
			else {
				return (EClass)UMLPackage.eINSTANCE.getEClassifier(selectedClassifierName) ;
			}
		}
		
	}
	
}

